/*
*Copyright 2021-2023 NERCIS
*
*Licensed under the Apache License, Version 2.0 (the "License");
*you may not use this file except in compliance with the License.
*You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*Unless required by applicable law or agreed to in writing, software
*distributed under the License is distributed on an "AS IS" BASIS,
*WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*See the License for the specific language governing permissions and
*limitations under the License.
*/

package cn.ac.nercis.pes.community.controller.evaluation.prepare;

import cn.ac.nercis.pes.common.constant.common.BaseConstants;
import cn.ac.nercis.pes.common.constant.evaluation.EvaluationModule;
import cn.ac.nercis.pes.common.constant.project.FinishState;
import cn.ac.nercis.pes.community.component.dialog.MessageDialog;
import cn.ac.nercis.pes.community.component.dialog.MessageType;
import cn.ac.nercis.pes.community.controller.base.GlobalEventHandle;
import cn.ac.nercis.pes.community.controller.base.InitEvalDataLoad;
import cn.ac.nercis.pes.community.utils.ControlUtils;
import cn.ac.nercis.pes.community.utils.*;
import cn.ac.nercis.pes.community.views.evaluation.prepare.PrepareView;
import cn.ac.nercis.pes.model.dto.project.SystemDetailDTO;
import cn.ac.nercis.pes.model.dto.project.SystemEvaluationDTO;
import cn.ac.nercis.pes.service.project.SystemService;
import javafx.application.Platform;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.net.URL;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 被测系统信息管理控制器
 * @author limy
 * @version 1.0.0
 */
@Slf4j
public class EvaluationInfSystemController implements Initializable, GlobalEventHandle, InitEvalDataLoad {

    @FXML
    private StackPane page;

    @FXML
    private Button saveButton;
    @FXML
    private Button tmpSaveButton;

    @FXML
    private ToggleGroup gradeProtectionGroup;
    @FXML
    private ToggleGroup serviceRangeGroup;
    @FXML
    private ToggleGroup serviceObjectGroup;
    @FXML
    private ToggleGroup coverageGroup;
    @FXML
    private ToggleGroup paSchemeGroup;
    @FXML
    private ToggleGroup ppSituationGroup;

    @FXML
    private RadioButton finishEvaRb;
    @FXML
    private RadioButton runEvaRb;
    @FXML
    private RadioButton noneEvaRb;
    @FXML
    private TextField finishEvaUnitTxt;
    @FXML
    private DatePicker finishEvaTimeTxt;
    @FXML
    private TextField finishEvaConTxt;
    @FXML
    private TextField runEvaUnitTxt;

    @FXML
    private RadioButton nationwideRb;
    @FXML
    private RadioButton interProvincialRb;
    @FXML
    private RadioButton wholeProvinceRb;
    @FXML
    private RadioButton interAreaRb;
    @FXML
    private RadioButton areaRb;
    @FXML
    private RadioButton otherRangeRb;
    @FXML
    private TextField interProvincialCountTxt;
    @FXML
    private TextField interAreaCountTxt;
    @FXML
    private TextField rangeDescTxt;

    @FXML
    private CheckBox otherServiceAreaCbx;
    @FXML
    private TextField otherServiceAreaDesc;

    @FXML
    private VBox serviceAreaVBox;

    @FXML
    private RadioButton internalRb;
    @FXML
    private RadioButton publicRb;
    @FXML
    private RadioButton bothRb;
    @FXML
    private RadioButton otherObjectRb;
    @FXML
    private TextField objectDescTxt;

    @FXML
    private RadioButton localRb;
    @FXML
    private RadioButton metropolitanRb;
    @FXML
    private RadioButton wanRb;
    @FXML
    private RadioButton otherCoverageRb;
    @FXML
    private TextField coverageDescTxt;

    @FXML
    private CheckBox privateCbx;
    @FXML
    private CheckBox internetCbx;
    @FXML
    private CheckBox otherNatureCbx;
    @FXML
    private TextField natureDescTxt;
    @FXML
    private TextField serviceUserCountTx;

    @FXML
    private RadioButton selectRunRb;
    @FXML
    private RadioButton unselectRunRb;
    @FXML
    private TextField runYearTxt;
    @FXML
    private TextField runMonthTxt;
    @FXML
    private TextField runDescTxt;

    @FXML
    private CheckBox otherIndustryCbx;
    @FXML
    private CheckBox thisIndustryCbx;
    @FXML
    private CheckBox thisUnitCbx;
    @FXML
    private CheckBox otherCbx;
    @FXML
    private TextField otherTxt;
    @FXML
    private TextField netNameTxt;

    @FXML
    private RadioButton passRb;
    @FXML
    private DatePicker passDateTxt;
    @FXML
    private CheckBox expertReviewCbx;
    @FXML
    private CheckBox unitReviewCbx;

    @FXML
    private TextField unitTxt;
    @FXML
    private RadioButton notPassRb;
    @FXML
    private RadioButton noneRb;

    @FXML
    private RadioButton useRb;
    @FXML
    private RadioButton notUseRb;
    @FXML
    private TextField countTxt;
    @FXML
    private TextField independentCountTxt;
    @FXML
    private TextField sharedCountTxt;
    @FXML
    private TextField certifiedCountTxt;
    @FXML
    private TextField uncertifiedCountTxt;
    @FXML
    private TextField foreignCountTxt;

    @FXML
    private HBox groupingAlgorithmHBox;
    @FXML
    private HBox asymmetricAlgorithmHBox;
    @FXML
    private HBox hashAlgorithmHBox;
    @FXML
    private HBox sequenceAlgorithmHBox;
    @FXML
    private CheckBox groupingOtherCbx;
    @FXML
    private TextField groupingOtherTxt;
    @FXML
    private CheckBox asymmetricOtherCbx;
    @FXML
    private TextField asymmetricOtherTxt;
    @FXML
    private CheckBox hashOtherCbx;
    @FXML
    private TextField hashOtherTxt;
    @FXML
    private CheckBox sequenceOtherCbx;
    @FXML
    private TextField sequenceOtherTxt;
    @FXML
    private TextField otherAlgorithmTxt;

    @FXML
    private ToggleGroup ciiGroup;
    @FXML
    private RadioButton selectCiiRb;
    @FXML
    private RadioButton unselectCiiRb;
    @FXML
    private TextField ciiDescTxt;

    @FXML
    private ToggleGroup cloudGroup;
    @FXML
    private RadioButton selectCloudRb;
    @FXML
    private RadioButton unselectCloudRb;
    @FXML
    private TextField cloudNameTxt;
    @FXML
    private ToggleGroup cloudSelectGroup;
    @FXML
    private RadioButton cloudPassRb;
    @FXML
    private RadioButton cloudRunRb;
    @FXML
    private RadioButton cloudNoneRb;
    @FXML
    private TextField cloudUnitTxt;
    @FXML
    private DatePicker cloudTimeTxt;
    @FXML
    private TextField cloudConTxt;


    private final SystemService systemService;
    protected final SimpleBooleanProperty dataSaving = new SimpleBooleanProperty(false);

    private String currentSystemId;
    private SystemDetailDTO currentSystemDetail;

    public EvaluationInfSystemController(){
        this.systemService = SpringUtils.getBean(SystemService.class);
    }
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        saveButton.setGraphic(IconUtils.getGlyph("save-button-icon","btn-icon"));
        tmpSaveButton.setGraphic(IconUtils.getGlyph("temp-save-button-icon","btn-icon"));
        saveButton.disableProperty().bind(dataSaving);
        tmpSaveButton.disableProperty().bind(dataSaving);
        this.initializeControl();
        GuiStore.applyQuickSave(this.page,this::onGlobalSave);
    }

    /**
     * 初始化数据
     * @param systemId 系统ID
     */
    @Override
    public void initializeData(String systemId){
        //显示保存并添加系统按钮
        this.currentSystemId = systemId;
        this.loadSystemEvaluation();
    }

    @Override
    public void onGlobalSave() {
        LogUtils.info(log, "执行快捷保存操作...");
        saveSystem(false);
    }

    @FXML
    public void onTmpSave(){
        LogUtils.info(log, "执行暂存操作...");
        saveSystem(false);
    }

    @FXML
    public void onFinishSave(){
        LogUtils.info(log, "执行保存操作...");
        saveSystem(true);
    }

    private void loadSystemEvaluation() {
        LogUtils.info(log, "获取被测系统基本信息...");
        LogUtils.info(log, "请求数据：{}", this.currentSystemId);
        CompletableFuture.supplyAsync(() -> this.systemService.findById(this.currentSystemId))
                .thenAccept(res -> Platform.runLater(() -> {
                    this.currentSystemDetail = res.getData();
                    initSystemEvaluationData(res.getData().getSystemEvaluation());
                }))
                .exceptionally((ex) -> {
                    log.error("获取被测系统基本信息出错!", ex);
                    return null;
                });
    }

    private void initializeControl(){
        this.ciiDescTxt.disableProperty().bind(selectCiiRb.selectedProperty().not());

        this.finishEvaUnitTxt.disableProperty().bind(this.finishEvaRb.selectedProperty().not());
        this.finishEvaTimeTxt.disableProperty().bind(this.finishEvaRb.selectedProperty().not());
        this.finishEvaConTxt.disableProperty().bind(this.finishEvaRb.selectedProperty().not());
        this.runEvaUnitTxt.disableProperty().bind(this.runEvaRb.selectedProperty().not());

        this.interProvincialCountTxt.disableProperty().bind(this.interProvincialRb.selectedProperty().not());
        this.interAreaCountTxt.disableProperty().bind(this.interAreaRb.selectedProperty().not());
        this.rangeDescTxt.disableProperty().bind(this.otherRangeRb.selectedProperty().not());

        this.otherServiceAreaDesc.disableProperty().bind(this.otherServiceAreaCbx.selectedProperty().not());

        this.objectDescTxt.disableProperty().bind(this.otherObjectRb.selectedProperty().not());

        this.coverageDescTxt.disableProperty().bind(this.otherCoverageRb.selectedProperty().not());
        this.natureDescTxt.disableProperty().bind(this.otherNatureCbx.selectedProperty().not());

        this.runYearTxt.disableProperty().bind(this.selectRunRb.selectedProperty().not());
        this.runMonthTxt.disableProperty().bind(this.selectRunRb.selectedProperty().not());
        this.runDescTxt.disableProperty().bind(this.unselectRunRb.selectedProperty().not());

        this.otherTxt.disableProperty().bind(this.otherCbx.selectedProperty().not());

        this.cloudNameTxt.disableProperty().bind(this.selectCloudRb.selectedProperty().not());
        this.cloudPassRb.disableProperty().bind(this.selectCloudRb.selectedProperty().not());
        this.cloudRunRb.disableProperty().bind(this.selectCloudRb.selectedProperty().not());
        this.cloudNoneRb.disableProperty().bind(this.selectCloudRb.selectedProperty().not());
        this.cloudUnitTxt.disableProperty().bind(this.selectCloudRb.selectedProperty().not());
        this.cloudTimeTxt.disableProperty().bind(this.selectCloudRb.selectedProperty().not());
        this.cloudConTxt.disableProperty().bind(this.selectCloudRb.selectedProperty().not());

        this.passDateTxt.disableProperty().bind(passRb.selectedProperty().not());
        this.expertReviewCbx.disableProperty().bind(passRb.selectedProperty().not());
        this.unitReviewCbx.disableProperty().bind(passRb.selectedProperty().not());
        this.unitTxt.disableProperty().bind(unitReviewCbx.selectedProperty().not());

        this.countTxt.disableProperty().bind(useRb.selectedProperty().not());
        this.independentCountTxt.disableProperty().bind(useRb.selectedProperty().not());
        this.sharedCountTxt.disableProperty().bind(useRb.selectedProperty().not());
        this.certifiedCountTxt.disableProperty().bind(useRb.selectedProperty().not());
        this.uncertifiedCountTxt.disableProperty().bind(useRb.selectedProperty().not());
        this.foreignCountTxt.disableProperty().bind(useRb.selectedProperty().not());

        this.groupingOtherTxt.disableProperty().bind(groupingOtherCbx.selectedProperty().not());
        this.asymmetricOtherTxt.disableProperty().bind(asymmetricOtherCbx.selectedProperty().not());
        this.hashOtherTxt.disableProperty().bind(hashOtherCbx.selectedProperty().not());
        this.sequenceOtherTxt.disableProperty().bind(sequenceOtherCbx.selectedProperty().not());
    }

    private void initSystemEvaluationData(SystemEvaluationDTO systemEvaluation){
        this.selectCiiRb.setSelected(StringUtils.equals(systemEvaluation.getCiiState(),selectCiiRb.getText()));
        this.unselectCiiRb.setSelected(StringUtils.equals(systemEvaluation.getCiiState(),unselectCiiRb.getText()));
        if(this.selectCiiRb.isSelected()){
            this.ciiDescTxt.setText(systemEvaluation.getCiiDesc());
        }

        this.finishEvaRb.setSelected(StringUtils.equals(systemEvaluation.getGradeProtectionState(),finishEvaRb.getText()));
        this.runEvaRb.setSelected(StringUtils.equals(systemEvaluation.getGradeProtectionState(),runEvaRb.getText()));
        this.noneEvaRb.setSelected(StringUtils.equals(systemEvaluation.getGradeProtectionState(),noneEvaRb.getText()));
        if(this.finishEvaRb.isSelected()){
            this.finishEvaUnitTxt.setText(systemEvaluation.getEvaluationUnitName());
            this.finishEvaTimeTxt.setValue(systemEvaluation.getEvaluationDate());
            this.finishEvaConTxt.setText(systemEvaluation.getConclusion());
        }
        if(this.runEvaRb.isSelected()){
            this.runEvaUnitTxt.setText(systemEvaluation.getEvaluationUnitName());
        }

        this.nationwideRb.setSelected(StringUtils.equals(systemEvaluation.getServiceRange(),this.nationwideRb.getText()));
        this.interProvincialRb.setSelected(StringUtils.equals(systemEvaluation.getServiceRange(),this.interProvincialRb.getText()));
        this.wholeProvinceRb.setSelected(StringUtils.equals(systemEvaluation.getServiceRange(),this.wholeProvinceRb.getText()));
        this.interAreaRb.setSelected(StringUtils.equals(systemEvaluation.getServiceRange(),this.interAreaRb.getText()));
        this.areaRb.setSelected(StringUtils.equals(systemEvaluation.getServiceRange(),this.areaRb.getText()));
        this.otherRangeRb.setSelected(StringUtils.equals(systemEvaluation.getServiceRange(),this.otherRangeRb.getText()));
        if(interProvincialRb.isSelected()){
            this.interProvincialCountTxt.setText(String.valueOf(systemEvaluation.getInterProvincialCount()));
        }
        if(interAreaRb.isSelected()){
            this.interAreaCountTxt.setText(String.valueOf(systemEvaluation.getInterAreaCount()));
        }
        if(otherRangeRb.isSelected()){
            this.rangeDescTxt.setText(systemEvaluation.getServiceRangeDesc());
        }

        this.initServiceAreaData(systemEvaluation);

        this.internalRb.setSelected(StringUtils.equals(systemEvaluation.getServiceObject(),internalRb.getText()));
        this.publicRb.setSelected(StringUtils.equals(systemEvaluation.getServiceObject(),publicRb.getText()));
        this.bothRb.setSelected(StringUtils.equals(systemEvaluation.getServiceObject(),bothRb.getText()));
        this.otherObjectRb.setSelected(StringUtils.equals(systemEvaluation.getServiceObject(),otherObjectRb.getText()));
        if(otherObjectRb.isSelected()){
            this.objectDescTxt.setText(systemEvaluation.getServiceObjectDesc());
        }

        this.localRb.setSelected(StringUtils.equals(systemEvaluation.getCoverage(), localRb.getText()));
        this.metropolitanRb.setSelected(StringUtils.equals(systemEvaluation.getCoverage(), metropolitanRb.getText()));
        this.wanRb.setSelected(StringUtils.equals(systemEvaluation.getCoverage(), wanRb.getText()));
        this.otherCoverageRb.setSelected(StringUtils.equals(systemEvaluation.getCoverage(), otherCoverageRb.getText()));
        if (otherCoverageRb.isSelected()) {
            this.coverageDescTxt.setText(systemEvaluation.getCoverageDesc());
        }

        List<String> networkNatures = new ArrayList<>();
        if (StringUtils.isNotBlank(systemEvaluation.getNetworkNature())) {
            networkNatures = Arrays.asList(StringUtils.split(systemEvaluation.getNetworkNature(), BaseConstants.MULTI_SPLIT_CHAR));
        }
        this.privateCbx.setSelected(networkNatures.stream().anyMatch(value -> StringUtils.equals(value, privateCbx.getText())));
        this.internetCbx.setSelected(networkNatures.stream().anyMatch(value -> StringUtils.equals(value, internetCbx.getText())));
        this.otherNatureCbx.setSelected(networkNatures.stream().anyMatch(value -> StringUtils.equals(value, otherNatureCbx.getText())));
        if (otherNatureCbx.isSelected()) {
            this.natureDescTxt.setText(systemEvaluation.getNetworkNatureDesc());
        }

        this.serviceUserCountTx.setText(systemEvaluation.getServiceUserCount());

        this.selectRunRb.setSelected(Objects.nonNull(systemEvaluation.getIsRunning())&&systemEvaluation.getIsRunning());
        this.unselectRunRb.setSelected(Objects.isNull(systemEvaluation.getIsRunning()) || (!systemEvaluation.getIsRunning()));
        if (selectRunRb.isSelected()) {
            this.runYearTxt.setText(systemEvaluation.getRunYear());
            this.runMonthTxt.setText(systemEvaluation.getRunMonth());
        } else {
            this.runDescTxt.setText(systemEvaluation.getRunDesc());
        }

        List<String> interconnections = new ArrayList<>();
        if (StringUtils.isNotBlank(systemEvaluation.getInterconnection())) {
            interconnections = Arrays.asList(StringUtils.split(systemEvaluation.getInterconnection(), BaseConstants.MULTI_SPLIT_CHAR));
        }
        this.otherIndustryCbx.setSelected(interconnections.stream().anyMatch(value -> StringUtils.equals(value, otherIndustryCbx.getText())));
        this.thisIndustryCbx.setSelected(interconnections.stream().anyMatch(value -> StringUtils.equals(value, thisIndustryCbx.getText())));
        this.thisUnitCbx.setSelected(interconnections.stream().anyMatch(value -> StringUtils.equals(value, thisUnitCbx.getText())));
        this.otherCbx.setSelected(interconnections.stream().anyMatch(value -> StringUtils.equals(value, otherCbx.getText())));
        if (this.otherCbx.isSelected()) {
            this.otherTxt.setText(systemEvaluation.getInterconnectionDesc());
        }
        this.netNameTxt.setText(systemEvaluation.getNetName());

        this.selectCloudRb.setSelected(StringUtils.equals(systemEvaluation.getCloudState(),selectCloudRb.getText()));
        this.unselectCloudRb.setSelected(StringUtils.equals(systemEvaluation.getCloudState(),unselectCloudRb.getText()));
        if(this.selectCloudRb.isSelected()){
            this.cloudNameTxt.setText(systemEvaluation.getCloudName());
            this.cloudPassRb.setSelected(StringUtils.equals(systemEvaluation.getCloudSelectState(),cloudPassRb.getText()));
            this.cloudRunRb.setSelected(StringUtils.equals(systemEvaluation.getCloudSelectState(),cloudRunRb.getText()));
            this.cloudNoneRb.setSelected(StringUtils.equals(systemEvaluation.getCloudSelectState(),cloudNoneRb.getText()));
            this.cloudUnitTxt.setText(systemEvaluation.getCloudUnit());
            this.cloudTimeTxt.setValue(systemEvaluation.getCloudDate());
            this.cloudConTxt.setText(systemEvaluation.getCloudCon());
        }

        this.passRb.setSelected(StringUtils.equals(systemEvaluation.getPaScheme(), passRb.getText()));
        this.notPassRb.setSelected(StringUtils.equals(systemEvaluation.getPaScheme(), notPassRb.getText()));
        this.noneRb.setSelected(StringUtils.equals(systemEvaluation.getPaScheme(),noneRb.getText()));
        if(passRb.isSelected()) {
            this.passDateTxt.setValue(systemEvaluation.getPassDate());
            List<String> schemeMethods = new ArrayList<>();
            if (StringUtils.isNotBlank(systemEvaluation.getPaSchemeMethod())) {
                schemeMethods = Arrays.asList(StringUtils.split(systemEvaluation.getPaSchemeMethod(), BaseConstants.MULTI_SPLIT_CHAR));
            }
            this.expertReviewCbx.setSelected(schemeMethods.stream().anyMatch(value -> StringUtils.equals(value, expertReviewCbx.getText())));
            this.unitReviewCbx.setSelected(schemeMethods.stream().anyMatch(value -> StringUtils.equals(value, unitReviewCbx.getText())));
            if (this.unitReviewCbx.isSelected()) {
                this.unitTxt.setText(systemEvaluation.getPaSchemeUnit());
            }
        }

        this.useRb.setSelected(StringUtils.equals(systemEvaluation.getPpSituation(),useRb.getText()));
        this.notUseRb.setSelected(StringUtils.equals(systemEvaluation.getPpSituation(),notUseRb.getText()));
        if(useRb.isSelected()){
            this.countTxt.setText(String.valueOf(systemEvaluation.getPpSituationCount()));
            this.independentCountTxt.setText(String.valueOf(systemEvaluation.getPpSituationIndependentCount()));
            this.sharedCountTxt.setText(String.valueOf(systemEvaluation.getPpSituationSharedCount()));
            this.certifiedCountTxt.setText(String.valueOf(systemEvaluation.getPpSituationCertifiedCount()));
            this.uncertifiedCountTxt.setText(String.valueOf(systemEvaluation.getPpSituationUnCertifiedCount()));
            this.foreignCountTxt.setText(String.valueOf(systemEvaluation.getPpSituationForeignCount()));
        }

        this.initAlgorithmData(groupingAlgorithmHBox,systemEvaluation.getGroupingAlgorithm());
        if(groupingOtherCbx.isSelected()){
            this.groupingOtherTxt.setText(systemEvaluation.getGroupingAlgorithmDesc());
        }
        this.initAlgorithmData(asymmetricAlgorithmHBox,systemEvaluation.getAsymmetricAlgorithm());
        if(asymmetricOtherCbx.isSelected()){
            this.asymmetricOtherTxt.setText(systemEvaluation.getAsymmetricAlgorithmDesc());
        }
        this.initAlgorithmData(hashAlgorithmHBox,systemEvaluation.getHashAlgorithm());
        if(hashOtherCbx.isSelected()){
            this.hashOtherTxt.setText(systemEvaluation.getHashAlgorithmDesc());
        }
        this.initAlgorithmData(sequenceAlgorithmHBox,systemEvaluation.getSequenceAlgorithm());
        if(sequenceOtherCbx.isSelected()){
            this.sequenceOtherTxt.setText(systemEvaluation.getSequenceAlgorithmDesc());
        }
        this.otherAlgorithmTxt.setText(systemEvaluation.getOtherAlgorithmDesc());
    }

    private void initServiceAreaData(SystemEvaluationDTO systemEvaluation){
        String[] selectedArea = StringUtils.split(systemEvaluation.getServiceScope(), BaseConstants.MULTI_SPLIT_CHAR);
        if(Objects.isNull(selectedArea) || selectedArea.length == 0){
            return;
        }
        List<CheckBox> areas = serviceAreaVBox.getChildren()
                .stream()
                .filter(n -> n instanceof HBox)
                .flatMap(n -> ((HBox) n).getChildren().stream())
                .filter(n -> n instanceof CheckBox)
                .map(n -> (CheckBox) n)
                .toList();
        List<String> selected = Arrays.asList(selectedArea);
        for(CheckBox cbx:areas){
            cbx.setSelected(selected.stream().anyMatch(s->StringUtils.equals(s,cbx.getText())));
        }
        if(this.otherServiceAreaCbx.isSelected()){
            this.otherServiceAreaDesc.setText(systemEvaluation.getServiceScopeDesc());
        }
    }

    private void initAlgorithmData(HBox box,String data){
        String[] selectedItems = StringUtils.split(data, BaseConstants.MULTI_SPLIT_CHAR);
        if(Objects.isNull(selectedItems) || selectedItems.length == 0){
            return;
        }
        List<CheckBox> areas = box.getChildren()
                .stream()
                .filter(n -> n instanceof CheckBox)
                .map(n -> (CheckBox) n)
                .toList();
        List<String> selected = Arrays.asList(selectedItems);
        for(CheckBox cbx:areas){
            cbx.setSelected(selected.stream().anyMatch(s->StringUtils.equals(s,cbx.getText())));
        }
    }

    private void saveSystem(boolean finish){
        try {
            collectSystemEvaluationData(this.currentSystemDetail.getSystemEvaluation());
        }catch (Exception ex){
            AppUtils.showMessageDialog(ex.getMessage(),MessageType.FAIL,this.page);
            log.error("收集数据期间出错：",ex);
            return;
        }
        CompletableFuture.supplyAsync(()->systemService.save(this.currentSystemDetail))
                .thenAccept(res-> Platform.runLater(()->{
                    if(res.isSuccess()){
                        this.refreshFinishProcess(finish);
                        MessageDialog.builder()
                                .withContainer(this.page)
                                .withType(MessageType.SUCCESS)
                                .withMessage("保存成功")
                                .build().show();
                    }else{
                        MessageDialog.builder()
                                .withContainer(this.page)
                                .withType(MessageType.FAIL)
                                .withMessage(res.getMsg())
                                .build().show();
                    }
                })).exceptionally((ex) -> {
                    this.dataSaving.setValue(false);
                    log.error("保存被测系统基本信息出错!", ex);
                    return null;
                });
    }

    private void refreshFinishProcess(boolean finish){
        var prepareView = AppStore.getEvaluationView(this.currentSystemId, PrepareView.class);
        if(prepareView.getController() instanceof PrepareController controller){
            controller.setEvalProcess(EvaluationModule.EVALUATION_INF_SYSTEM, finish ? FinishState.FINISH:FinishState.INCOMPLETE);
        }
    }

    private void collectSystemEvaluationData(SystemEvaluationDTO systemEvaluation) throws Exception{
        systemEvaluation.setCiiState(getSelectedRadioText(ciiGroup));
        systemEvaluation.setCiiDesc(selectCiiRb.isSelected()?ciiDescTxt.getText():StringUtils.EMPTY);

        systemEvaluation.setGradeProtectionState(getSelectedRadioText(gradeProtectionGroup));
        systemEvaluation.setEvaluationUnitName(finishEvaUnitTxt.getText());
        systemEvaluation.setEvaluationDate(finishEvaTimeTxt.getValue());
        systemEvaluation.setConclusion(finishEvaConTxt.getText());
        if(runEvaRb.isSelected()){
            systemEvaluation.setEvaluationUnitName(runEvaUnitTxt.getText());
        }

        systemEvaluation.setServiceRange(getSelectedRadioText(serviceRangeGroup));
        if(interProvincialRb.isSelected()){
            systemEvaluation.setInterProvincialCount(ControlUtils.toInteger(interProvincialCountTxt,"跨省（区、市）个数无效"));
        }
        if(interAreaRb.isSelected()){
            systemEvaluation.setInterAreaCount(ControlUtils.toInteger(interAreaCountTxt,"跨地（市、区）个数无效"));
        }
        if(otherRangeRb.isSelected()){
            systemEvaluation.setServiceRangeDesc(rangeDescTxt.getText());
        }
        this.collectServiceAreaData(systemEvaluation);
        systemEvaluation.setServiceObject(getSelectedRadioText(serviceObjectGroup));
        if(otherObjectRb.isSelected()){
            systemEvaluation.setServiceObjectDesc(objectDescTxt.getText());
        }

        systemEvaluation.setCoverage(getSelectedRadioText(coverageGroup));
        if(otherCoverageRb.isSelected()){
            systemEvaluation.setCoverageDesc(coverageDescTxt.getText());
        }
        String networkNature = Stream.of(privateCbx,internetCbx,otherNatureCbx)
                .filter(CheckBox::isSelected)
                .map(CheckBox::getText)
                .collect(Collectors.joining(BaseConstants.MULTI_SPLIT_CHAR));
        systemEvaluation.setNetworkNature(networkNature);
        if(otherNatureCbx.isSelected()){
            systemEvaluation.setNetworkNatureDesc(natureDescTxt.getText());
        }
        systemEvaluation.setServiceUserCount(serviceUserCountTx.getText());

        systemEvaluation.setIsRunning(selectRunRb.isSelected());
        if(systemEvaluation.getIsRunning()){
            systemEvaluation.setRunYear(runYearTxt.getText());
            systemEvaluation.setRunMonth(runMonthTxt.getText());
        }else{
            systemEvaluation.setRunDesc(runDescTxt.getText());
        }
        String interconnection = Stream.of(otherIndustryCbx,thisIndustryCbx,thisUnitCbx,otherCbx)
                .filter(CheckBox::isSelected)
                .map(CheckBox::getText)
                .collect(Collectors.joining(BaseConstants.MULTI_SPLIT_CHAR));
        systemEvaluation.setInterconnection(interconnection);
        if(otherCbx.isSelected()){
            systemEvaluation.setInterconnectionDesc(otherTxt.getText());
        }
        systemEvaluation.setNetName(netNameTxt.getText());

        systemEvaluation.setCloudState(getSelectedRadioText(cloudGroup));
        if(selectCloudRb.isSelected()){
            systemEvaluation.setCloudName(cloudNameTxt.getText());
            systemEvaluation.setCloudSelectState(getSelectedRadioText(cloudSelectGroup));
            systemEvaluation.setCloudUnit(cloudUnitTxt.getText());
            systemEvaluation.setCloudDate(cloudTimeTxt.getValue());
            systemEvaluation.setCloudCon(cloudConTxt.getText());
        }

        systemEvaluation.setPaScheme(getSelectedRadioText(paSchemeGroup));
        if(passRb.isSelected()){
            systemEvaluation.setPassDate(passDateTxt.getValue());
            String schemeMethod = Stream.of(expertReviewCbx,unitReviewCbx)
                    .filter(CheckBox::isSelected)
                    .map(CheckBox::getText)
                    .collect(Collectors.joining(BaseConstants.MULTI_SPLIT_CHAR));
            systemEvaluation.setPaSchemeMethod(schemeMethod);
            if(unitReviewCbx.isSelected()){
                systemEvaluation.setPaSchemeUnit(unitTxt.getText());
            }
        }

        systemEvaluation.setPpSituation(getSelectedRadioText(ppSituationGroup));
        if(useRb.isSelected()){
            systemEvaluation.setPpSituationCount(ControlUtils.toInteger(countTxt,"系统使用的密码产品数量无效"));
            systemEvaluation.setPpSituationIndependentCount(ControlUtils.toInteger(independentCountTxt,"系统使用的密码产品，独立使用数量无效"));
            systemEvaluation.setPpSituationSharedCount(ControlUtils.toInteger(sharedCountTxt,"系统使用的密码产品，共享使用数量无效"));
            systemEvaluation.setPpSituationCertifiedCount(ControlUtils.toInteger(certifiedCountTxt,"系统使用的密码产品，取得认证数量无效"));
            systemEvaluation.setPpSituationUnCertifiedCount(ControlUtils.toInteger(uncertifiedCountTxt,"系统使用的密码产品，未取得认证数量无效"));
            systemEvaluation.setPpSituationForeignCount(ControlUtils.toInteger(foreignCountTxt,"系统使用的密码产品，国外产品数量无效"));
        }

        systemEvaluation.setGroupingAlgorithm(collectAlgorithmData(groupingAlgorithmHBox));
        if(groupingOtherCbx.isSelected()){
            systemEvaluation.setGroupingAlgorithmDesc(groupingOtherTxt.getText());
        }
        systemEvaluation.setAsymmetricAlgorithm(collectAlgorithmData(asymmetricAlgorithmHBox));
        if(asymmetricOtherCbx.isSelected()){
            systemEvaluation.setAsymmetricAlgorithmDesc(asymmetricOtherTxt.getText());
        }
        systemEvaluation.setHashAlgorithm(collectAlgorithmData(hashAlgorithmHBox));
        if(hashOtherCbx.isSelected()){
            systemEvaluation.setHashAlgorithmDesc(hashOtherTxt.getText());
        }
        systemEvaluation.setSequenceAlgorithm(collectAlgorithmData(sequenceAlgorithmHBox));
        if(sequenceOtherCbx.isSelected()){
            systemEvaluation.setSequenceAlgorithmDesc(sequenceOtherTxt.getText());
        }
        systemEvaluation.setOtherAlgorithmDesc(otherAlgorithmTxt.getText());
    }

    private String getSelectedRadioText(ToggleGroup toggleGroup){
        return Optional.ofNullable((RadioButton) toggleGroup.getSelectedToggle())
                .map(RadioButton::getText)
                .orElse("");
    }

    private void collectServiceAreaData(SystemEvaluationDTO systemEvaluation){
        systemEvaluation.setServiceScope(serviceAreaVBox.getChildren().stream()
                .filter(n->n instanceof HBox)
                .flatMap(n->((HBox) n).getChildren().stream())
                .filter(n->n instanceof CheckBox)
                .map(n->(CheckBox)n)
                .filter(CheckBox::isSelected)
                .map(CheckBox::getText)
                .collect(Collectors.joining(BaseConstants.MULTI_SPLIT_CHAR)));
        if(otherServiceAreaCbx.isSelected()){
            systemEvaluation.setServiceScopeDesc(otherServiceAreaDesc.getText());
        }
    }

    private String collectAlgorithmData(HBox box){
        return box.getChildren()
                .stream()
                .filter(n->n instanceof CheckBox)
                .map(n->(CheckBox)n)
                .filter(CheckBox::isSelected)
                .map(CheckBox::getText)
                .collect(Collectors.joining(BaseConstants.MULTI_SPLIT_CHAR));
    }
}